#!/usr/bin/env python
# -*- coding: utf-8 -*-

from typing import Any

from cta.interface.action.close_position.abstract_close_not_main_contract_action import \
    AbstractCloseNotMainContractAction
from web.constants.close_position_reason import ClosePositionReason
from web.constants.direction import Direction
from web.domain.main_contract import MainContract
from web.domain.responsibility_chain_dto import ResponsibilityChainDto
from web.manager.log_manager import LogManager
from web.models import CommodityFutureInfo
from web.models.commodity_future_date_contract_data import CommodityFutureDateContractData
from web.models.optimize2_commodity_future_transaction_record import Optimize2CommodityFutureTransactionRecord
from web.models.quant2_commodity_future_transaction_record import Quant2CommodityFutureTransactionRecord
from web.util.commodity_future_code_util import CommodityFutureCodeUtil

Logger = LogManager.get_logger(__name__)

class Optimize2CloseNotMainContractAction(AbstractCloseNotMainContractAction):
    """
    动量因子策略，平仓非主力合约
    """

    def exec(self, responsibility_chain_dto: ResponsibilityChainDto = None) -> Any:
        Logger.info("动量因子策略，平仓非主力合约")

        transaction_date: str = responsibility_chain_dto.transaction_date

        # 查询主力合约
        main_contract_list: list[MainContract] = self.commodity_future_date_contract_data_dao.find_main_contract_by_transaction_date(transaction_date)
        if main_contract_list is not None and len(main_contract_list) > 0:

            # 查询所有持仓记录
            not_close_optimize2_commodity_future_transaction_record_list: list[Optimize2CommodityFutureTransactionRecord] = self.optimize2_commodity_future_transaction_record_dao.find_not_close_position()
            if not_close_optimize2_commodity_future_transaction_record_list is not None and len(not_close_optimize2_commodity_future_transaction_record_list) > 0:
                for not_close_optimize2_commodity_future_transaction_record in not_close_optimize2_commodity_future_transaction_record_list:
                    if not_close_optimize2_commodity_future_transaction_record.code not in list(map(lambda x: x.code, main_contract_list)):
                        Logger.info("期货[%s]是非主力合约，平仓", not_close_optimize2_commodity_future_transaction_record.code)

                        # 期货收盘价
                        filter_dict: dict = {'code': not_close_optimize2_commodity_future_transaction_record.code, 'transaction_date': transaction_date}
                        commodity_future_date_contract_data: CommodityFutureDateContractData = self.commodity_future_date_contract_data_dao.find_one(filter_dict, dict(), dict())

                        if commodity_future_date_contract_data is None:
                            # 说明期货在这一天没有交易记录
                            Logger.info("期货[%s]在日期[%s]没有交易记录，开始查找前一个交易日的记录", not_close_optimize2_commodity_future_transaction_record.code, transaction_date)

                            # 如果在某一天没有开盘价，比如暂停交易，则查找最近一个交易日的开盘价
                            commodity_future_date_contract_data = self.commodity_future_date_contract_data_dao.find_last_commodity_future_date_contract_data_by_code_and_date(not_close_optimize2_commodity_future_transaction_record.code, transaction_date)

                        # 查询commodity_future_info记录（大小写不敏感的精确匹配查询）
                        filter_dict = {'code__iexact': CommodityFutureCodeUtil.code_to_contract_code(commodity_future_date_contract_data.code)}
                        commodity_future_info: CommodityFutureInfo = self.commodity_future_info_dao.find_one(filter_dict, dict(), list())

                        # 查询optimize2_c_f_transact_record表中的记录
                        optimize2_commodity_future_transaction_record: Optimize2CommodityFutureTransactionRecord = Optimize2CommodityFutureTransactionRecord()
                        if not_close_optimize2_commodity_future_transaction_record.direction == Direction.Up:
                            filter_dict = {'code': not_close_optimize2_commodity_future_transaction_record.code, 'direction': Direction.Up, 'sell_date__isnull': True,
                                           'buy_date': not_close_optimize2_commodity_future_transaction_record.buy_date, 'account_name': not_close_optimize2_commodity_future_transaction_record.account_name}
                            optimize2_commodity_future_transaction_record = self.optimize2_commodity_future_transaction_record_dao.find_one(filter_dict, dict(), list())
                        if not_close_optimize2_commodity_future_transaction_record.direction == Direction.Down:
                            filter_dict = {'code': not_close_optimize2_commodity_future_transaction_record.code, 'direction': Direction.Down, 'buy_date__isnull': True,
                                           'sell_date': not_close_optimize2_commodity_future_transaction_record.sell_date, 'account_name': not_close_optimize2_commodity_future_transaction_record.account_name}
                            optimize2_commodity_future_transaction_record = self.optimize2_commodity_future_transaction_record_dao.find_one(filter_dict, dict(), list())

                        if optimize2_commodity_future_transaction_record is None:
                            Logger.warning("账户[%s]没持有期货[%s]，所以跳过", not_close_optimize2_commodity_future_transaction_record.account_name, not_close_optimize2_commodity_future_transaction_record.code)
                            continue

                        # 平仓
                        self.optimize2_commodity_future_transaction_record_dao.update_when_close_position(not_close_optimize2_commodity_future_transaction_record.direction,
                            transaction_date, commodity_future_date_contract_data.close_price, commodity_future_info,
                            not_close_optimize2_commodity_future_transaction_record.buy_lot if not_close_optimize2_commodity_future_transaction_record.direction == Direction.Up else not_close_optimize2_commodity_future_transaction_record.sell_lot,
                            ClosePositionReason.Close_Not_Main_Contract, optimize2_commodity_future_transaction_record.id_)
            else:
                Logger.info("没有持仓的期货，不用平仓非主力合约")
        else:
            Logger.warning("日期[%s]查询不到主力合约", transaction_date)

        super().next(responsibility_chain_dto)